﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using Isuka.Excel.Dynamic;
using Isuka.Excel.Iteration;
using Isuka.Iteration;

namespace Isuka.Excel
{
    partial class XExtensions
    {
        public static IIterable<XRangeLinerIterator> GetRowsIterable(this IXGrid grid)
        {
            Contract.Requires<ArgumentNullException>(grid != null, "grid");

            var rows = grid.Rows;
            return new XRangeLinerIterable(rows, rows.Count, XDirection.Down);
        }

        public static IEnumerable<dynamic> ToDynamicRows(this IXGrid source)
        {
            Contract.Requires<ArgumentNullException>(source != null, "source");
            Contract.Ensures(Contract.Result<IEnumerable<dynamic>>() != null);

            return ToDynamicRowsIterator(source);

        }
        static IEnumerable<dynamic> ToDynamicRowsIterator(this IXGrid source)
        {
            Contract.Requires(source != null);

            var rc = source.Rows.Count;
            for (var i = 0; i < rc; i++)
            {
                yield return new DynamicRow(source, i);
            }
        }

        /// <summary>
        /// 列をモデルに変換する
        /// 直接モデルを作成するなら、こちらのほうが早い
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="source"></param>
        /// <param name="rowToModel"></param>
        /// <returns></returns>
        public static IEnumerable<TModel> ToModels<TModel>(this IXGrid source, Func<dynamic, TModel> rowToModel)
        {
            Contract.Requires<ArgumentNullException>(source != null, "source");
            Contract.Requires<ArgumentNullException>(rowToModel != null, "rowToModel");
            Contract.Ensures(Contract.Result<IEnumerable<TModel>>() != null);

            return ToModelsIterator(source, rowToModel);
        }

        static IEnumerable<TModel> ToModelsIterator<TModel>(this IXGrid source, Func<dynamic, TModel> rowToModel)
        {
            Contract.Requires(source != null);
            Contract.Requires(rowToModel != null);

            var rc = source.Rows.Count;
            var row = new DynamicRow(source);
            for (var i = 0; i < rc; i++, row.CurrentRow++)
            {
                yield return rowToModel(row);
            }
        }
    }
}
